package com.file.manage.infrastructure.base;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import java.util.Arrays;
import java.util.Objects;

/**
 * @ClassName: Property
 * @author: hsy
 * @date: 2022/5/7 14:02
 * @description:
 */
public interface Property {
    boolean like(Property p);

    static Property of(Object o1, Object o2) {
        return new TwoProperty(o1, o2);
    }

    static Property of(Object o1, Object o2, Object o3) {
        return new ThreeProperty(o1, o2, o3);
    }

    static Property of(Object... o) {
        return new AnyProperty(o);
    }

    class TwoProperty implements Property {
        Object o1, o2;

        private TwoProperty(Object o1, Object o2) {
            if (ObjectUtil.isEmpty(o1)) {
                o1 = null;
            }
            if (ObjectUtil.isEmpty(o2)) {
                o2 = null;
            }
            this.o1 = o1;
            this.o2 = o2;
        }

        @Override
        public boolean like(Property p) {
            if (p instanceof TwoProperty) {
                if (o1 != null && !o1.equals(((TwoProperty) p).o1)) {
                    return false;
                }
                if (o2 != null && !o2.equals(((TwoProperty) p).o2)) {
                    return false;
                }
                return true;
            } else if (p instanceof ThreeProperty) {
                if (o1 != null && !o1.equals(((ThreeProperty) p).o1)) {
                    return false;
                }
                if (o2 != null && !o2.equals(((ThreeProperty) p).o2)) {
                    return false;
                }
                return true;
            } else {

                AnyProperty anyProperty = (AnyProperty) p;
                if (anyProperty.o.length < 2) {
                    return false;
                }
                if (o1 != null && !o1.equals(anyProperty.o[0])) {
                    return false;
                }
                if (o2 != null && !o2.equals(anyProperty.o[1])) {
                    return false;
                }

                return true;
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            TwoProperty that = (TwoProperty) o;
            return Objects.equals(o1, that.o1) &&
                    Objects.equals(o2, that.o2);
        }

        @Override
        public int hashCode() {
            return Objects.hash(o1, o2);
        }

        @Override
        public String toString() {
            if (o1 == null && o2 == null) {
                return "";
            }
            StringBuffer buffer = new StringBuffer();
            if (o1 != null) {
                buffer.append(o1 + "_");
            }
            if (o2 != null) {
                buffer.append(o2);
            }
            String s = buffer.toString();
            // 去掉末尾的 _
            String last = s.substring(s.length() - 1);
            if ("_".equals(last)) {
                s = s.substring(0, s.length() - 1);
            }
            return s;
        }
    }

    class ThreeProperty implements Property {
        Object o1, o2, o3;

        private ThreeProperty(Object o1, Object o2, Object o3) {
            if (ObjectUtil.isEmpty(o1)) {
                o1 = null;
            }
            if (ObjectUtil.isEmpty(o2)) {
                o2 = null;
            }
            if (ObjectUtil.isEmpty(o3)) {
                o3 = null;
            }
            this.o1 = o1;
            this.o2 = o2;
            this.o3 = o3;
        }

        @Override
        public boolean like(Property p) {
            if (p instanceof TwoProperty) {
                return false;
            } else if (p instanceof ThreeProperty) {
                if (o1 != null && !o1.equals(((ThreeProperty) p).o1)) {
                    return false;
                }
                if (o2 != null && !o2.equals(((ThreeProperty) p).o2)) {
                    return false;
                }
                if (o3 != null && !o3.equals(((ThreeProperty) p).o3)) {
                    return false;
                }
                return true;
            } else {

                AnyProperty anyProperty = (AnyProperty) p;
                if (anyProperty.o.length < 3) {
                    return false;
                }
                if (o1 != null && !o1.equals(anyProperty.o[0])) {
                    return false;
                }
                if (o2 != null && !o2.equals(anyProperty.o[1])) {
                    return false;
                }
                if (o3 != null && !o3.equals(anyProperty.o[2])) {
                    return false;
                }

                return true;
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ThreeProperty that = (ThreeProperty) o;
            return Objects.equals(o1, that.o1) &&
                    Objects.equals(o2, that.o2) &&
                    Objects.equals(o3, that.o3);
        }

        @Override
        public int hashCode() {
            return Objects.hash(o1, o2, o3);
        }

        @Override
        public String toString() {
            if (o1 == null && o2 == null && o3 == null) {
                return "";
            }
            StringBuffer buffer = new StringBuffer();
            if (o1 != null) {
                buffer.append(o1 + "_");
            }
            if (o2 != null) {
                buffer.append(o2 + "_");
            }
            if (o3 != null) {
                buffer.append(o3);
            }
            String s = buffer.toString();
            // 去掉末尾的 _
            String last = s.substring(s.length() - 1);
            if ("_".equals(last)) {
                s = s.substring(0, s.length() - 1);
            }
            return s;
        }
    }

    class AnyProperty implements Property {

        Object[] o;

        private AnyProperty(Object[] o) {
            this.o = o;
            for (int i = 0; i < o.length; i++) {
                if (ObjectUtil.isEmpty(o[i])) {
                    o[i] = null;
                }
            }
        }

        @Override
        public boolean like(Property p) {
            AnyProperty anyProperty;
            if (p instanceof TwoProperty) {
                TwoProperty tp = (TwoProperty) p;
                anyProperty = new AnyProperty(new Object[]{tp.o1, tp.o2});
            } else if (p instanceof ThreeProperty) {
                ThreeProperty wp = (ThreeProperty) p;
                anyProperty = new AnyProperty(new Object[]{wp.o1, wp.o2, wp.o3});
            } else {
                anyProperty = (AnyProperty) p;
            }

            if (anyProperty.o.length < o.length) {
                return false;
            }

            for (int i = 0; i < o.length; i++) {
                if (o[i] != null && !o[i].equals(anyProperty.o[i])) {
                    return false;
                }
            }
            return true;
        }

        @Override
        public boolean equals(Object o1) {
            if (this == o1) return true;
            if (o1 == null || getClass() != o1.getClass()) return false;
            AnyProperty that = (AnyProperty) o1;
            return Arrays.equals(o, that.o);
        }

        @Override
        public int hashCode() {
            return Arrays.hashCode(o);
        }

        @Override
        public String toString() {
            StringBuffer buffer = new StringBuffer();
            for (int i = 0; i < o.length; i++) {
                if (ObjectUtil.isNotEmpty(o[i])) {
                    buffer.append(o[i] + "_");
                }
            }
            String s = buffer.toString();
            if (StrUtil.isBlank(s)) {
                return "";
            }
            // 去掉末尾的 _
            String last = s.substring(s.length() - 1);
            if ("_".equals(last)) {
                s = s.substring(0, s.length() - 1);
            }
            return s;
        }
    }
}
